<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./js/lil-gui.module.min.js"></script>
</head>

<body>
    <canvas id="canvas" style="width: 800px; height: 600px;"></canvas>
</body>

<script id="vertex-shader" type="nojs">
    attribute vec2 a_position;

    uniform vec2 u_resolution;
    uniform vec2 u_translation;
    uniform vec2 u_rotation;
    uniform vec2 u_scale;

    void main() {
        // 缩放
        vec2 scaledPosition = a_position * u_scale;

        // 旋转位置
        vec2 rotatedPosition = vec2(
            scaledPosition.x * u_rotation.y + scaledPosition.y * u_rotation.x,
            scaledPosition.y * u_rotation.y - scaledPosition.x * u_rotation.x
        );

        // 加上平移量
        vec2 position = rotatedPosition + u_translation;

        // 通过矩阵变换将坐标转换到裁剪空间0-1
        vec2 zeroToOne = position / u_resolution;

        // 将0-1的坐标转换到0-2
        vec2 zeroToTwo = zeroToOne * 2.0;

        // 将0-2的坐标转换到-1-1
        vec2 clipSpace = zeroToTwo - 1.0;

        gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
    }
</script>

<script id="flagment-shader" type="nojs">
    precision mediump float;
    uniform vec4 u_color;

    void main() {
        gl_FragColor = u_color;
    }
</script>

<script type="module">
    import { GUI } from './js/lil-gui.module.min.js';

    const gui = new GUI();

    function main() {
        var canvas = document.querySelector("#canvas");
        canvas.width = 800;
        canvas.height = 600;

        const gl = document.getElementById('canvas').getContext('webgl');
        if (!gl) {
            console.log('Failed to get the rendering context for WebGL');
            return;
        }

        const vertexShader = createShader(gl, gl.VERTEX_SHADER, document.getElementById('vertex-shader').text);
        const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, document.getElementById('flagment-shader').text);

        const shaderProgram = initShaderProgram(gl, vertexShader, fragmentShader);

        const positionAttributeLocation = gl.getAttribLocation(shaderProgram, 'a_position');

        const resolutionUniformLocation = gl.getUniformLocation(shaderProgram, 'u_resolution');

        const colorUniformLocation = gl.getUniformLocation(shaderProgram, "u_color");

        const translationLocation = gl.getUniformLocation(shaderProgram, "u_translation");

        const rotationLocation = gl.getUniformLocation(shaderProgram, "u_rotation");

        const scaleLocation = gl.getUniformLocation(shaderProgram, "u_scale");

        // attribute 需要从缓冲区中获取数据
        const positionBuffer = gl.createBuffer();

        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

        // 通过bufferData将数据传入缓冲区
        setGeometry(gl);

        gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

        // 设置背景颜色蓝色
        gl.clearColor(0, 0, 0, 255);
        // gl.clearColor(0, 1, 1, 0);
        gl.clear(gl.COLOR_BUFFER_BIT);

        gl.useProgram(shaderProgram);

        gl.enableVertexAttribArray(positionAttributeLocation); // 开启attribute变量

        gl.uniform2f(resolutionUniformLocation, gl.canvas.width, gl.canvas.height);
        gl.uniform4f(colorUniformLocation, Math.random(), Math.random(), Math.random(), 1);

        gl.uniform2fv(rotationLocation, [0, 1])
        gl.uniform2fv(scaleLocation, [1, 1])


        // 告诉attribute变量从缓冲区中获取数据
        const size = 2; // 每次迭代运行提取两个单位数据
        const type = gl.FLOAT; // 每个单位的数据类型是32位浮点型
        const normalize = false; // 不需要归一化数据
        const stride = 0; // 0 = 移动单位数量 * 每个单位占用内存（sizeof(type)）
        var offset = 0; // 从缓冲区何处开始获取数据
        gl.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset);

        const primitiveType = gl.TRIANGLES;
        var offset = 0;
        var count = 18;
        gl.drawArrays(primitiveType, offset, count);

        const resolutionSize = {
            width: gl.canvas.width,
            height: gl.canvas.height
        }

        let currentPos = {
            x: 10,
            y: 10,
            rotateAngle: 0,
            width: 100,
            height: 60,
            scale: [1, 1]
        }



        gui.add(currentPos, 'x', 0, resolutionSize.width - currentPos.width).name('X位置').onChange(() => {
            // 设置平移
            const translation = [currentPos.x, currentPos.y];
            gl.uniform2fv(translationLocation, translation);

            gl.clearColor(0, 0, 0, 255);
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.drawArrays(primitiveType, offset, count);
        })

        gui.add(currentPos, 'y', 0, resolutionSize.height - currentPos.height).name('Y位置').onChange(() => {
            const translation = [currentPos.x, currentPos.y];
            gl.uniform2fv(translationLocation, translation);

            gl.clearColor(0, 0, 0, 255);
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.drawArrays(primitiveType, offset, count);
        })
        gui.add(currentPos, 'rotateAngle', 0, 360).name('旋转角度').onChange(() => {

            const angleInRadians = currentPos.rotateAngle * Math.PI / 180;
            const cos = Math.cos(angleInRadians);
            const sin = Math.sin(angleInRadians);
            gl.uniform2fv(rotationLocation, [sin, cos])
            gl.clearColor(0, 0, 0, 255);
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.drawArrays(primitiveType, offset, count);
        })
        gui.add(currentPos.scale, '0', -5, 5).name('x缩放').onChange(() => {
            console.log(currentPos.scale)
            gl.uniform2fv(scaleLocation, [currentPos.scale[0], currentPos.scale[1]])
            gl.clearColor(0, 0, 0, 255);
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.drawArrays(primitiveType, offset, count);
        })
        gui.add(currentPos.scale, '1', -5, 5).name('y缩放').onChange(() => {
            console.log(currentPos.scale)
            gl.uniform2fv(scaleLocation, [currentPos.scale[0], currentPos.scale[1]])
            gl.clearColor(0, 0, 0, 255);
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.drawArrays(primitiveType, offset, count);
        })

    }

    function setGeometry(gl) {
        gl.bufferData(
            gl.ARRAY_BUFFER,
            new Float32Array([
                // 左竖
                0, 0,
                30, 0,
                0, 150,
                0, 150,
                30, 0,
                30, 150,

                // 上横
                30, 0,
                100, 0,
                30, 30,
                30, 30,
                100, 0,
                100, 30,

                // 中横
                30, 60,
                67, 60,
                30, 90,
                30, 90,
                67, 60,
                67, 90,
            ]),
            gl.STATIC_DRAW);
    }

    function setRectangle(gl, x, y, width, height) {
        const x1 = x;
        const x2 = x + width;
        const y1 = y;
        const y2 = y + height;

        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
            x1, y1,
            x2, y1,
            x1, y2,
            x1, y2,
            x2, y1,
            x2, y2,
        ]), gl.STATIC_DRAW);
    }

    function createShader(gl, type, source) {
        const shader = gl.createShader(type);
        gl.shaderSource(shader, source);
        gl.compileShader(shader);
        var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
        if (success) {
            return shader;
        }
        gl.deleteShader(shader);
    }

    function initShaderProgram(gl, vertexShader, fragmentShader) {
        const shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertexShader)
        gl.attachShader(shaderProgram, fragmentShader)
        gl.linkProgram(shaderProgram)
        var success = gl.getProgramParameter(shaderProgram, gl.LINK_STATUS);
        if (success) {
            return shaderProgram;
        }
        gl.deleteProgram(shaderProgram);
    }

    main();


</script>

</html>